// -*- c++ -*-
/**************************************************************/
/*  This file is licensed from, and is a trade secret of:     */
/*                                                            */
/*    Mercury Computer Systems, Incorporated                  */
/*    199 Riverneck Road                                      */
/*    Chelmsford, Massachusetts 01824-2820                    */
/*    United States of America                                */
/*    Telephone + 1 978 256-1300                              */
/*                                                            */
/*  Refer to your Software License Agreement for provisions   */
/*  on use, duplication, or disclosure.                       */
/*  US. Government users and prime contractors are also       */
/*  governed by the following Data Rights Notice:             */
/*  Use, duplication or disclosure by the US. Government is   */
/*  subject to the provisions set forth in FAR 52.227-14 for  */
/*  restricted rights or other agency data rights provisions  */
/*  on commercial software and documentation, as applicable.  */
/*                                                            */
/*  This file: (a) was developed at private expense, and no   */
/*  part was developed with government funds, (b) is a        */
/*  trade secret of Mercury Computer Systems, Inc. for the    */
/*  purposes of the Freedom of Information Act, (c) is        */
/*  "commercial computer software" subject to limited         */
/*  utilization as provided in the above noted Software       */
/*  License Agreement and (d) is in all respects data         */
/*  belonging exclusively to Mercury Computer Systems, Inc..  */
/*                                                            */
/**************************************************************/

/******************************************************************/
/* Copyright (c) 1999-2003, Mercury Computer Systems, Inc.,       */
/* Chelmsford MA.,and all third party embedded software sources.  */
/* All rights reserved under the Copyright laws of US. and        */
/* international treaties.                                        */
/*                                                                */
/* Patent Pending                                                 */
/******************************************************************/


//$COPYRIGHT_END

#ifndef FM3TR_H__
#define FM3TR_H__

#include "CF__Resource_impl.h"
#include "AudioPort_impl.h"
#include "SceOsThreadManager.h"
#include "mc_error.h"

#include "mac_port.h"

#ifdef _WIN32
#ifndef FM3TR_EXPORTS
#define FM3TR_IMPORT __declspec(dllimport)
#else
#define FM3TR_IMPORT __declspec(dllexport)
#endif
#else
#define FM3TR_IMPORT
#endif // _WIN32


struct FM3TR_IMPORT FM3TR_Constants {
  static int Preamble_Phasing_Bits;
  static int Preamble_Guard_Time_Bits;
  static int Preamble_Bits_Per_Block;
  static int Hops_Per_Frame;
  static int Bits_Per_Frame;
  static int Symbols_Per_Frame;
  static int Nrt;
  static int Ninf;
  static int Ntt;
  static int Ngt;
  static unsigned long A_Code;
  static unsigned long S_Code;

  enum {
    DATA_2000_HPS,
    VOICE_2000_HPS,
    DATA_1000_HPS,
    VOICE_1000_HPS,
    DATA_500_HPS,
    VOICE_500_HPS,
    DATA_250_HPS,
    VOICE_250_HPS
  };
};


class FM3TR_IMPORT FM3TR_WaveformPacketizer : public CF__Resource_impl
{
public:
  static status Create (FM3TR_WaveformPacketizer *&, const char * identifier);

  virtual ~FM3TR_WaveformPacketizer ();

  status Init ();

  // From CF::Resource
  void start ()
    throw (CORBA::SystemException, CF::Resource::StartError);
  void stop ()
    throw (CORBA::SystemException, CF::Resource::StopError);

  // From CF::PortSupplier
  CORBA::Object_ptr getPort (const CORBA::Char * name)
    throw (CORBA::SystemException, CF::PortSupplier::UnknownPort);

  // From SDR_FM3TR::LLC_Control
  virtual void startStream ()
    throw (CORBA::SystemException);
  virtual void stopStream ()
    throw (CORBA::SystemException);


protected:
  FM3TR_WaveformPacketizer (const char * identifier);
  // Separate thread master function	
  static void RunWorker (void * param);
  // Inner loop function that deals with external commands
  status RunLoop ();
  // Inner loop method that performs component business logic
  status Run ();

  SCE::OS::ThreadManager m_thread;
  bool m_threadrunning;
  bool m_bStop;

private:
  void SendPreamble (int mode);
  void EncodeFrame (bool eom);

  int m_operational_mode;
  bool m_voice_mode;
  char * m_phasing_pattern;
  char * m_a_code;
  char * m_s_code;
  char * m_inv_s_code;
  char * m_input;
  int m_input_count;
  int m_num_read;
  int m_output_count;
  char * m_output_frame;    // output buffer for frame data
  char * m_output_preamble; // output buffer for preamble data
  int m_count;
  bool m_llc_enable;            // LLC Control variable
  bool m_llc_ctrl_disable;      // Prop value which turns LLC Control on/off

  // Port object references
  CvsdInPort_impl *m_cvsdin;
  Fm3trOutPort_impl *m_fm3trout;

  // MAC/LLC Interface definitions
  LLC_Ctrl_InPort_impl<FM3TR_WaveformPacketizer> *m_llc_ctrl_in;
};

class FM3TR_IMPORT FM3TR_WaveformReceiver : virtual public CF__Resource_impl
{
public:
  static status Create (FM3TR_WaveformReceiver *&, const char * identifier);

  FM3TR_WaveformReceiver (const char *identifier);
  ~FM3TR_WaveformReceiver ();

  // From CF::Resource
  void start ()
    throw (CORBA::SystemException, CF::Resource::StartError);
  void stop ()
    throw (CORBA::SystemException, CF::Resource::StopError);

  // From CF::PortSupplier
  CORBA::Object_ptr getPort (const CORBA::Char * name)
    throw (CORBA::SystemException, CF::PortSupplier::UnknownPort);

protected:
  // Separate thread master function	
  static void RunWorker (void * param);
  // Inner loop function that deals with external commands
  status RunLoop();
  // Inner loop method that performs component business logic
  status Run ();

  SCE::OS::ThreadManager m_thread;
  bool m_threadrunning;
  bool m_bStop;

private:
  bool Acquire (int & mode, unsigned long &pattern);
  bool ExtractHop ();
  bool Sync (bool & eom);

  bool InitCorrelator (unsigned long & pattern, int shift = 32);
  bool Correlate (unsigned long & pattern,
		  unsigned long code,
		  int threshold,
		  bool & positive,
		  int max_skip = -1,
		  int expected_shift = -1);
  int CountBits (unsigned long);

  bool ReadMore (int count = 1);
  bool EatBits (int count);
  int m_operational_mode;
  bool m_voice_mode;

  /*
   * THRESHOLD is the threshold for auto-correlation.
   * SKIP_MATCH is the number of bits that we skip ahead after
   * matching a code; must be greater than zero and less than 32.
   */

  enum {
    THRESHOLD = 25, // allows for three bit flips
    SKIP_MATCH = 30
  };

  /*
   * INTRA_PREAMBLE_TIMEOUT is the timeout for matching codes within the
   * preamble (matching the S-Code after matching the A-Code). If this
   * timeout expires, we reacquire instead.
   *
   * SYNC_TIMEOUT is the timeout spent looking for the S-Code in a sync
   * hop. If this timeout expires, we reacquire. Should be less than the
   * number of bits in the phasing pattern, or we might miss the A-Code.
   */

  enum {
    INTRA_PREAMBLE_TIMEOUT = 100,
    SYNC_TIMEOUT = 64 // originally set to 1000
  };

  static int m_bitcount[16]; // static array for counting bits quickly

  int m_input_count;    // number of samples currently in the input buffer
  int m_samples_read;   // number of samples that have been read from the input buffer
  char * m_input;       // pointer to beginning of input data buffer
  int m_input_buffer_size;

  int m_output_count;  // number of samples currently in the output buffer
  char * m_output;

  // Port object references
  Fm3trInPort_impl *m_fm3trin; // usesPort
  CvsdOutPort_impl *m_cvsdout; // providesPort

  // MAC Interface definitions
  MAC_Ctrl_OutPort_impl<SDR_FM3TR::MAC_Signaling::MAC_FlowControl_Local> *m_mac_fc_out;
};

inline int
FM3TR_WaveformReceiver::CountBits (unsigned long value)
{
  return m_bitcount[value & 15] +
    m_bitcount[(value >> 4) & 15] +
    m_bitcount[(value >> 8) & 15] +
    m_bitcount[(value >> 12) & 15] +
    m_bitcount[(value >> 16) & 15] +
    m_bitcount[(value >> 20) & 15] +
    m_bitcount[(value >> 24) & 15] +
    m_bitcount[(value >> 28) & 15];
}

#endif
